/******************************************************************************
//             INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in accordance with the terms of that agreement.
//    Copyright(c) 2000 - 2001 Intel Corporation. All Rights Reserved.
//
//  VSS: 
//     $Workfile: $
//     $Revision: $
//     $Date:     $
//     $Archive:  $
//
//  Description:
//      Intel(R) Integrated Performance Primitives - JPEG Helper file.
//      This file contains Huffman decoding (Baseline) functions.
//
//  History:
//     Date         Author        Changes
//     2000/5/22   Jerry Hu       Created (Version 0.1 Baseline)
//
********************************************************************************/
#include "_ippjpeg.h"
#include "ijdhufsh.h"

/******************************************************************************
// Name:             ippiDecodeHuffman_Direct_JPEG_1u16s
// Description:      Decodes 8x8 block from huffman stream.
// Input Arguments: 
//             pSrc: Identifies source huffman stream data.
//      pSrcBitsLen: Indicates the number of bits that have been decoded before.
//          pDCPred: Identifies the previous DC value of prediction.
//  pPrefetchedBits: Identifies prefetch buffer which contain the bits decoded 
//                   in the last time.
// pNumValidPrefetchedBits:
//                   Indicates number of valid bits in prefetch buffer.
//     pDCHuffTable: Identifies "IppJPEGDeHuffTable" data structure for DC decoding.
//     pACHuffTable: Identifies "IppJPEGDeHuffTable" data structure for AC decoding.
//
// Output Arguments:
//             pDst: Identifies destination data in 8x8.
//          pDCPred: Identifies the current DC value of prediction.
//          pMarker: Identifies the marker decoded from stream.
//  pPrefetchedBits: Identifies prefetch buffer which contain the bits decoded 
//                   in current time.
// pNumValidPrefetchedBits:
//                   Indicates number of valid bits in prefetch buffer.
//
// Remarks:      
//                   1. The start address of "pDst" shall be aligned at 4byte boundary.
//                   2. It is better to do this alignment at 32byte boundary to optimize 
//                      D-Cache accessing.
//                   3. *pDCPred shall be 0 in initial or after each restart interval.
//                   4. *pMarker shall be 0 in initial or after it was processed.
//                   5. *pNumValidPrefetchedBits shall be 0 in following case
//                      1) Initial.
//                      2) After each restart interval.
//                      3) After each marker.
//
// Returns:         
//    IPP_STATUS_OK: Succeeds.
// IPP_STATUS_ERROR: Decoding error.
******************************************************************************/
IPPFUN(IppStatus, ippiDecodeHuffman_Direct_JPEG_1u16s)(const Ipp8u       *pSrc,
                                                      int               *pSrcBitsLen,
                                                      Ipp16s            *pDst,
                                                      Ipp16s            *pDCPred,
                                                      int               *pMarker,
                                                      Ipp32u            *pPrefetchedBits,
                                                      int               *pNumValidPrefetchedBits,
                                                      const IppJPEGDeHuffTable 
                                                                        *pDCHuffTable,
                                                      const IppJPEGDeHuffTable 
                                                                        *pACHuffTable)

{
    int k;  
    int nLen;
    int value;
    int rrrr, ssss, rs;

    _stream stream;

    _IPP_CHECK_ARG(NULL!=pSrc);
    _IPP_CHECK_ARG((NULL!=pSrcBitsLen)&&(0<=*pSrcBitsLen));
    _IPP_CHECK_ARG(NULL!=pDst);
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pDst));
    _IPP_CHECK_ARG(NULL!=pDCPred);
    _IPP_CHECK_ARG(NULL!=pMarker);
    _IPP_CHECK_ARG(NULL!=pPrefetchedBits);
    _IPP_CHECK_ARG(NULL!=pNumValidPrefetchedBits);
    _IPP_CHECK_ARG(0<=*pNumValidPrefetchedBits);
    _IPP_CHECK_ARG(NULL!=pDCHuffTable);
    _IPP_CHECK_ARG(NULL!=pACHuffTable);

    nLen=(*pSrcBitsLen>>3);
    stream.pHeadStreamBuffer=pSrc;
    stream.pStreamBuffer=&pSrc[nLen];
    stream.nUsedBytesLen=nLen;
    stream.pMarker=pMarker;
    stream.pnPrefetchedBits=pPrefetchedBits;
    stream.pnNumValidBits=pNumValidPrefetchedBits;

    for (k=0; k<64; k++) {
        pDst[k]=0;
    }
    

    /* Decode DC coef */
    ssss=_IppHuffDecode(pDCHuffTable,&stream);

    if (0>ssss) {
        return (IppStatus)((-256==ssss)?IPP_STATUS_OK:IPP_STATUS_ERROR);
    }

    if (ssss) {
        ssss&=0x0f; /* Make sure s is in [0,15] */
        _CHECKPREVIEWBITSNUM(ssss, &stream, IPP_STATUS_ERROR);

        _GETBITS(value, ssss, &stream);

        if (value<(1<<(ssss-1))) {
           value+=_nLowestCoef[ssss]; /* Negative Value */
        }

        *pDCPred = (Ipp16s)(*pDCPred+value);
    } /* if (ssss) */

    *pDst = (Ipp16s)(*pDCPred);


    /* Decode AC coefficient */
    for (k=1; k<64; ) {
        rs=_IppHuffDecode(pACHuffTable, &stream);
        if (0>rs) {
            if (-256==rs) {
                *pNumValidPrefetchedBits=0;
                *pSrcBitsLen=((stream.nUsedBytesLen)<<3);
                return IPP_STATUS_OK;
            }
            return IPP_STATUS_ERROR;
        }

        rrrr  = (rs>>4);
        ssss  = rs&0x0f;

        if (ssss) {
           k+=rrrr;
           _CHECKPREVIEWBITSNUM(ssss, &stream, IPP_STATUS_ERROR);
      
           _GETBITS(value, ssss, &stream);
      
           pDst[_nIppIZigZagIndex[k]] = (Ipp16s)( (value<(1<<(ssss-1)))?
                                              (value+_nLowestCoef[ssss]):
                                               value);
            k++;
        } else { /* Found zeros */
            if (15==rrrr) {
                k+=16;
            } else {/* Find EOB */
                break; 
            }
        } /* if (ssss) */

    } /* for (i=63; i>0; ) */

    /* Adjust the current point in the stream buffer */
    *pSrcBitsLen=((stream.nUsedBytesLen)<<3);

    return IPP_STATUS_OK;
}

/* EOF */
